<template>
  <div class="container">
    <!--头部筛选 start-->
    <div class="flex-row justify-between p_b10">
      <div>
        <el-input size="small" v-model="params.filter" placeholder="搜索关键词..." class="m_r10 width200"></el-input>
        <el-button size="small" type="primary" icon="el-icon-search" @click="onPageChange(1)"></el-button>
        <el-button size="small" type="primary" @click="onPageChange(1)">刷新</el-button>
      </div>
      <div>
        <el-button size="small" type="primary" @click="toggleEditorModal(true)">新增</el-button>
      </div>
    </div>
    <!--头部筛选 end-->

    <!--列表数据 start-->
    <el-table :data="tableData" border size="mini">
      <el-table-column prop="id" label="ID" width="55" align="center"></el-table-column>
      <el-table-column prop="title" :min-width="200" label="标题"></el-table-column>
      <el-table-column prop="status" :min-width="120" align="center" label="状态">
        <template v-slot="{row}">
          <el-tag type="success" v-if="row.status==='1'">启用</el-tag>
          <el-tag type="info" v-else>禁用</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="content" :min-width="200" align="center" label="封面图">
        <template v-slot="{row}">
          <img @click="onImgPreview(row.content.cover||'')"
               alt="" class="pointer cover-image"
               :src="row.content.cover" v-if="row.content.cover"/>
        </template>
      </el-table-column>
      <el-table-column prop="content" :min-width="300" align="center" label="内容">
        <template v-slot="{row}">
          <el-tooltip :content="row.content.content||''">
            <div class="intro-box">
              {{ row.content.content || "" }}
            </div>
          </el-tooltip>
        </template>
      </el-table-column>

      <el-table-column prop="content" :min-width="300" align="center" label="详情图">
        <template v-slot="{row}">
          <div class="flex-row flex-wrap">
            <img @click="onImgPreview(item||'')"
                 alt="" class="pointer intro-image" :src="item"
                 v-for="(item,i) of row.content.images||[]" :key="i"/>
          </div>
        </template>
      </el-table-column>

      <el-table-column label="操作" :width="120" align="center" fixed="right">
        <template #default="{row}">
          <el-button
              type="text" icon="el-icon-edit"
              @click="toggleEditorModal(true, row)"
              size="mini">编辑
          </el-button>
          <el-button type="text" icon="el-icon-delete" @click="onDestroy(row)" size="mini">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!--列表数据 end-->


    <!--分页组件 start-->
    <div class="pagination">
      <el-pagination
          background layout="total, prev, pager, next"
          :current-page="pageMeta.current_page"
          :page-size="pageMeta.limit" :total="pageMeta.total"
          @current-change="onPageChange"></el-pagination>
    </div>
    <!--分页组件 end-->

    <!--分类编辑、新增弹框 start-->
    <el-dialog
        v-model="formData.show"
        :title="formData.data.id>0?'编辑':'新增'"
        width="600px">
      <el-form
          ref="formRefName"
          :rules="rules"
          :model="formData.data" label-width="120px">
        <el-form-item label="新闻标题" prop="title">
          <el-input v-model="formData.data.title" placeholder="请填写新闻标题" maxlength="50"></el-input>
        </el-form-item>
        <el-form-item label="状态：">
          <el-radio-group v-model="formData.data.status">
            <el-radio label="1">启用</el-radio>
            <el-radio label="2">禁用</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="新闻内容" prop="content">
          <el-input type="textarea" v-model="formData.data.content" placeholder="请填写新闻内容"></el-input>
        </el-form-item>
        <el-form-item label="封面图">
          <div class="flex-row">
            <el-upload
                drag
                :before-upload="onBeforeUpload"
                action="#">
              <UploadFilled
                  :width="100"
                  v-if="!formData.cover||formData.cover.trim().length===0"/>
              <img class="qualifications" alt="" :src="formData.cover" v-else/>
            </el-upload>
          </div>
        </el-form-item>
        <el-form-item label="详情图">
          <el-upload
              v-if="formData.show"
              action="#"
              :on-remove="(_,files)=>formData.images = files"
              :file-list="formData.images"
              :on-preview="onImgPreview"
              :before-upload="onUpload"
              list-type="picture-card">
            <div style="height: 100%;" class="col-align-center">
              <Plus style="width: 40px;height: 40px"/>
            </div>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button size="small" @click="toggleEditorModal(false)">取消</el-button>
          <el-button size="small" type="primary" @click="onSubmit()">提交</el-button>
        </div>
      </template>
    </el-dialog>
    <!--分类编辑、新增弹框 end-->


    <!--分类编辑、新增弹框 start-->

    <!--图片查看器start-->
    <el-dialog
        v-model="viewer.imgViewer"
        title=""
        width="60%">
      <div class="row-align-center">
        <el-image alt="" :key="viewer.imgUrl" :src="viewer.imgUrl"/>
      </div>
    </el-dialog>
    <!--图片查看器end-->
  </div>


</template>

<script>
import {defineComponent, reactive, ref, toRaw} from "vue"
import {usePageMeta} from "../../hooks/usePageTableData";
import {deepClone, isString} from "../../utils/helpers";
import Toast from "../../utils/Toast";
import News from "../../api/modules/News";
import Media from "../../api/modules/Media";
import {Plus, UploadFilled} from "@element-plus/icons-vue";

export default defineComponent({
  name: "News",
  components: {
    Plus,
    UploadFilled,
  },
  data() {
    return {
      // 表单路由验证规则 参考： https://element-plus.gitee.io/zh-CN/component/form.html#%E8%A1%A8%E5%8D%95%E6%A0%A1%E9%AA%8C
      rules: {
        title: [
          {required: true, message: "请填写新闻标题"}
        ],
        content: [
          {required: true, message: "请填写新闻内容"}
        ],
      },
    }
  },
  setup() {
    const formRefName = ref(null);
    const pageHandle = usePageMeta(); // 公共的分页表单数据
    const params = reactive({
      filter: "",
    });
    const tableData = ref([]);


    onPageChange(1); // 初始化时直接请求一次分类列表
    const viewer = reactive({ // 图片查看器数据
      imgViewer: false,
      imgUrl: "",
    })
    const formData = reactive({ // 新增编辑弹框的表单数据
      show: false, // 是否打开表单
      images: [],
      cover: '',
      data: {
        id: 0, // id===0:新增操作，id>0:编辑操作
        title: '',
        status: '1',
        content: '',

      }
    });

    const _formData = deepClone(toRaw(formData)); // 拷贝一份原始的表单数据（用于还原数据使用）

    /**
     * 打开、关闭新增编辑弹框
     * @param show true :打开 false 关闭
     * @param data
     */
    function toggleEditorModal(show, data = {}) {
      formData.show = show;
      if (show) { // 打开新增编辑弹框
        const content = data.content || {}
        formData.data = Object.assign(
            {}, // Object.assign 会填充到第一项的参数，使用一个{}空对象 防止数据污染
            _formData.data, // 备份的原始数据
            data, // 编辑时该数据不为空 可填充 覆盖 原始数据_formData.data
            content,
        );
        formData.cover = content.cover || '';
        formData.images = (content.images || []).map(v => {
          return {
            name: v,
            url: v,
          }
        });
      } else {
        formData.data = _formData.data;
        formData.cover = '';
        formData.images = [];
      }
      if (formRefName.value) {
        formRefName.value.resetFields(); // 清除表单的验证信息
      }

    }

    // 新增、编辑提交
    function onSubmit() {
      if (!formRefName.value) {
        Toast.error('找不到表单')
        return;
      }
      formRefName.value.validate(async (valid) => {
        if (!valid) { // 表单验证不通过
          return;
        }
        // 拷贝一份表单数据
        const _formData = deepClone(toRaw(formData)).data;
        try {
          let res = {};

          // 组装新闻内容
          const content = {
            images: formData.images.map(v => v.url),
            content: _formData.content,
            cover: formData.cover,
          }
          // 组装提交内容
          const subData = {
            id: _formData.id,
            title: _formData.title,
            status: _formData.status,
            content: JSON.stringify(content)
          }
          if (subData.id > 0) { // 编辑操作
            res = await News.update(subData)
            onPageChange(); // 成功则刷新当前页面数据
          } else { // 新增操作
            delete subData.id;
            res = await News.create(subData);
            onPageChange(1); // 成功则刷新页面 （新增操作 将请求第一页的数据）
          }
          Toast.success(res.message || '操作成功');
          toggleEditorModal(false); //关闭新增、编辑弹框
        } catch (e) { // 新增、编辑操作提交错误或者失败
          Toast.error(e.message);
        }

      })
    }

    // 删除一行数据
    async function onDestroy(row) {
      const canDestroy = await Toast.confirm();
      if (!canDestroy) { // 用户选择了取消操作
        return;
      }
      try {
        const res = await News.destroy(row.id);
        Toast.success(res.message || '删除成功');
        // 删除成功刷新数据
        if (tableData.value.length === 1) {
          onPageChange(1); // 当前页面删除只剩最后一条时，请求第一页。
        } else {
          onPageChange(); // 否则刷新当前页面即可

        }
      } catch (e) {
        console.log(e)
        Toast.error(e.message || '删除失败')
      }
    }

    /**
     * 获取列表数据
     * @param page 页码 当page===undefined时表示刷新当前页面
     * @returns {Promise<void>}
     */
    async function onPageChange(page) {
      const pageMeta = deepClone(toRaw(pageHandle.pageMeta.value)); // 拷贝一份分页配置参数
      if (page) { // 存在页码时 请求页面
        pageMeta.index = page; // @注1
      }
      try {
        const {data} = await News.lists({
          ...pageMeta, // 公共分页数据（页码、每页请求数量等）
          ...params, // 筛选参数（关键词搜索等额外参数）
        });
        tableData.value = (data.data || []).map(v => {
          try {
            // content存贮的是一个json字符串{cover,content,images}
            v.content = JSON.parse(v.content) || {};
          } catch (e) {
            v.content = {}
          }
          return v
        }); // 取到数据后直接覆盖旧的列表数据即可
        pageHandle.updatePageMeta(pageMeta.index, data.count); // 取到数据后，更新公共的分页配置数据（@注1）

      } catch (e) {
        console.log(e);
      }
    }

    // 上传封面图
    async function onBeforeUpload(file) {
      Media.upload(file).then(async ({data}) => {
        if (!data || !data.url) {
          Toast.warning('图片上传异常');
          return;
        }
        formData.cover = data.url; // 设置到教师注册数据
      }).catch(e => {
        Toast.warning(e.message || '上传失败')
      })
      // https://element-plus.gitee.io/zh-CN/component/upload.html#drag-to-upload
      return Promise.reject(false); // 阻止le-upload组件的自动上传
    }

    // 其它（详情）图片上传
    function onUpload(file) {
      Media.upload(file).then(({data}) => {
        if (data) {
          formData.images.push(data);
        }
      }).catch(console.log)
      return false
    }

    // 图片预览
    function onImgPreview(file) {
      viewer.imgViewer = true;
      if (isString(file)) { // 字符串表示这是一个链接
        viewer.imgUrl = file;
      } else { // 否则是一个File对象
        viewer.imgUrl = file.url;

      }
    }

    return {
      ...pageHandle,
      params,
      viewer,
      onUpload,
      onImgPreview,
      onBeforeUpload,
      onSubmit,
      formData,
      formRefName,
      toggleEditorModal,
      onDestroy,
      tableData,
      onPageChange,
    }
  },
})
</script>

<style lang="scss" scoped>
.intro-box {
  max-height: 70px;
  overflow: hidden;
}

.cover-image {
  max-width: 200px;

}

.intro-image {
  max-width: 50px;
  margin: 2px;
}
</style>
